//
//  WXWaveView.m
//
//  Created by WelkinXie on 16/4/20.
//  Copyright © 2016年 WelkinXie. All rights reserved.
//
//  Github: https://github.com/WelkinXie/WXWaveView
//

#import "WXWaveView.h"
#import "WXWeakObject.h"

@interface WXWaveView ()

@property (assign, nonatomic) CGFloat offsetX;
@property (strong, nonatomic) CADisplayLink *waveDisplayLink;

@end

@implementation WXWaveView

- (void)dealloc {
    [self.waveDisplayLink invalidate];
    self.waveDisplayLink = nil;
}

+ (instancetype)addToView:(UIView *)view withFrame:(CGRect)frame {
    WXWaveView *waveView = [[self alloc] initWithFrame:frame];
    waveView.userInteractionEnabled = YES;
    [view addSubview:waveView];
    return waveView;
}

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self basicSetup];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    if ([super initWithCoder:aDecoder]) {
        [self basicSetup];
    }
    return self;
}

- (void)basicSetup {
    _angularSpeed = 2.f;
    _waveSpeed = 9.f;
    _waveTime = 1.5f;
    _waveColor = [UIColor whiteColor];
    
    [self currentWave];
}

- (BOOL)wave {
    if (self.waveShapeLayer.path) {
        return NO;
    }
    self.waveShapeLayer = [CAShapeLayer layer];
    self.waveShapeLayer.fillColor = self.waveColor.CGColor;
    [self.layer addSublayer:self.waveShapeLayer];

    self.waveDisplayLink = [CADisplayLink displayLinkWithTarget:[WXWeakObject weakObjectWithRealTarget:self] selector:@selector(currentWave)];
    [self.waveDisplayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    return YES;
}

- (void)currentWave {
    self.offsetX -= (self.waveSpeed * self.superview.frame.size.width / 320);
    
    CGFloat width = CGRectGetWidth(self.frame);
    CGFloat height = 15;
    
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path, NULL, 0, height / 2);

    CGFloat y = 0.f;
    for (CGFloat x = 0.f; x <= width ; x++) {
        y = height * sin(0.01 * (self.angularSpeed * x + self.offsetX));
        CGPathAddLineToPoint(path, NULL, x, y);
    }

    CGPathAddLineToPoint(path, NULL, width, height);
    CGPathAddLineToPoint(path, NULL, width, self.frame.size.height);
    CGPathAddLineToPoint(path, NULL, 0, self.frame.size.height);
    CGPathAddLineToPoint(path, NULL, 0, height);
    
    CGPathCloseSubpath(path);
    self.waveShapeLayer.path = path;
    CGPathRelease(path);
    
    if (self.backgroundColor != [UIColor clearColor]) {
        self.backgroundColor = [UIColor clearColor];
    }
    
}

- (void)resizeAndStopWave:(CGRect)toRect completion:(void (^)(BOOL finished))completion {
    [self.waveDisplayLink invalidate];
    self.waveDisplayLink = nil;
    self.waveShapeLayer.path = nil;
    
    self.alpha = 1.f;
    
    [UIView animateWithDuration:animationDurations animations:^{
        self.frame = toRect;
    }completion:^(BOOL finished) {
        if(completion){
            completion(finished);
        }
        self.backgroundColor = MainBlueColor;
    }];
    
    CGFloat width = CGRectGetWidth(self.frame);
    CGFloat height = 0;
    
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path, NULL, 0, 0);
    CGPathAddLineToPoint(path, NULL, width, 0);
    CGPathAddLineToPoint(path, NULL, width, height);
    CGPathAddLineToPoint(path, NULL, width, self.frame.size.height);
    CGPathAddLineToPoint(path, NULL, 0, self.frame.size.height);
    CGPathAddLineToPoint(path, NULL, 0, height);
    
    CGPathCloseSubpath(path);
    
    self.waveShapeLayer.path = path;
    CGPathRelease(path);
}

- (void)resizeAndStopWave:(CGRect)toRect {
    if (self.waveDisplayLink) {
        [self.waveDisplayLink invalidate];
        self.waveDisplayLink = nil;
    }

    self.waveShapeLayer.path = nil;
    self.alpha = 1.f;
    
    [UIView animateWithDuration:animationDurations animations:^{
        self.frame = toRect;
    }];
    
    CGFloat width = CGRectGetWidth(self.frame);
    CGFloat height = 0;
    
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path, NULL, 0, 0);
    CGPathAddLineToPoint(path, NULL, width, 0);
    CGPathAddLineToPoint(path, NULL, width, height);
    CGPathAddLineToPoint(path, NULL, width, self.frame.size.height);
    CGPathAddLineToPoint(path, NULL, 0, self.frame.size.height);
    CGPathAddLineToPoint(path, NULL, 0, height);
    
    CGPathCloseSubpath(path);
    
    self.waveShapeLayer.path = path;
    CGPathRelease(path);
}

- (void)resizeAndStartWave:(CGRect)toRect {
    self.waveShapeLayer.path = nil;
    [self wave];
    
//    [UIView animateWithDuration:animationDurations *  animations:^{
//        self.frame = toRect;
//    }];
    
    [UIView animateWithDuration:animationDurations delay:0.2 options:UIViewAnimationOptionCurveEaseOut animations:^{
        self.frame = toRect;
    } completion:^(BOOL finished) {
        self.waveShapeLayer.path = nil;
        [self wave];
    }];
}

- (void)resizeAndStartWave:(CGRect)toRect completion:(void (^)(BOOL finished))completion {
    
//    self.waveShapeLayer.path = nil;
//    [self wave];
    
    [UIView animateWithDuration:0.3 delay:0.1 options:UIViewAnimationOptionCurveEaseIn animations:^{
        self.frame = toRect;
    }completion:^(BOOL finished) {
        self.waveShapeLayer.path = nil;
        [self wave];
        
        if (completion) {
            completion(finished);
        }
    }];
}

- (void)stop {
    [UIView animateWithDuration:1.f animations:^{
        self.alpha = 0.f;
    } completion:^(BOOL finished) {
        [self.waveDisplayLink invalidate];
        self.waveDisplayLink = nil;
        self.waveShapeLayer.path = nil;
        self.alpha = 1.f;
    }];
}

@end
